﻿/**************************************************************
 *
 * 唯一标识：8564b939-8576-4f30-bb59-6a72accfaf46
 * 命名空间：Sgr.Identity
 * 创建时间：2023/8/21 11:40:40
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using System;
using System.Text;

namespace Sgr.Identity
{
    /// <summary>
    /// JWT配置参数
    /// </summary>
    public class JwtOptions
    {
        private string _key = string.Empty;
        private byte[]? _keyBytes;

        /// <summary>
        /// 签发者
        /// </summary>
        public string Issuer { get; set; } = string.Empty;

        /// <summary>
        /// 接收者
        /// </summary>
        public string Audience { get; set; } = string.Empty;

        /// <summary>
        /// 密钥
        /// </summary>
        public string Key
        {
            get => _key;
            set
            {
                if (_key != value)
                {
                    _key = value ?? string.Empty;
                    // 当 Key 改变时，重新计算 KeyBytes
                    _keyBytes = string.IsNullOrEmpty(_key) ? null : Encoding.UTF8.GetBytes(_key);
                }
            }
        }

        /// <summary>
        /// 密钥的字节数组形式，当 Key 改变时自动更新
        /// </summary>
        public byte[] KeyBytes
        {
            get
            {
                // 确保 KeyBytes 始终与 Key 同步
                if (_keyBytes == null && !string.IsNullOrEmpty(_key))
                {
                    _keyBytes = Encoding.UTF8.GetBytes(_key);
                }
                return _keyBytes ?? Array.Empty<byte>();
            }
        }

        /// <summary>
        /// 令牌过期时间（默认20分钟）
        /// </summary>
        public int ExpireSeconds { get; set; }

        /// <summary>
        /// 刷新令牌过期时间（默认720分钟）
        /// </summary>
        public int RefreshTokenExpireMinutes { get; set; }

        /// <summary>
        /// 刷新令牌是否仅支持HTTPS传输
        /// </summary>
        public bool RefreshTokenSecure { get; set; } = true;

        /// <summary>
        /// 指定Cookie在跨站请求中的发送行为，这有助于减少跨站请求伪造（CSRF）等安全威胁
        /// <para>None: 无论请求是否来自同一站点，都会发送Cookie。这可能会增加安全风险，但在某些情况下是必要的，例如，当第三方网站需要读取Cookie时</para>
        /// <para>Lax: 默认情况下，Cookie会随同站点的请求一起发送。但是，如果请求是通过链接（如a标签）导航到的，即使该请求来自另一个站点，Cookie也会一起发送。这种设置可以在不影响用户体验的前提下提供一定的安全保护</para>
        /// <para>Strict: 只有在请求来自同一站点时才发送Cookie。这是为了防止CSRF攻击，但也可能影响第三方网站的功能</para>
        /// </summary>
        public string RefreshTokenSameSite { get; set; } = "None";

        /// <summary>
        /// 过期时间容错值，解决服务器端时间不同步问题（秒）
        /// </summary>
        public int ClockSkewSeconds { get; set; }

        /// <summary>
        /// 刷新令牌Cookie的名称
        /// </summary>
        public string? RefreshTokenCookieName { get; set; }

        /// <summary>
        /// 刷新令牌Cookie的域名限制
        /// </summary>
        public string? RefreshTokenDomain { get; set; }

        /// <summary>
        /// 刷新令牌Cookie的Path限制
        /// </summary>
        public string? RefreshTokenPath { get; set; }

        /// <summary>
        /// 创建缺省配置项
        /// </summary>
        /// <returns></returns>
        public static JwtOptions CreateDefault()
        {
            return new JwtOptions()
            {
                Audience = "SGR",
                ExpireSeconds = 1200,
                RefreshTokenExpireMinutes = 720,
                Issuer = "SGR",
                Key = Guid.NewGuid().ToString("D").ToUpper(),
                ClockSkewSeconds = 30,
                RefreshTokenCookieName = "__Host-refresh_token"
            };
        }
    }
}